home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-04-28 | 6.8 KB | 330 lines | [TEXT/MPS ] |
- #ifndef __PARSER__
- #include "Parser.h"
- #endif
-
- #ifndef __PARSERACTIONS__
- #include "ParserActions.h"
- #endif
-
- #ifndef __CSCANNER__
- #include "CScanner.h"
- #endif
-
- #ifndef __FORMATTING__
- #include "Formatting.h"
- #endif
-
- #ifndef __CDENT__
- #include "cdent.h"
- #endif
-
- #ifndef __STACK__
- #include "Stack.h"
- #endif
-
- #ifndef __NEW__
- #include <new.h>
- #endif
-
- #ifndef __STRING__
- #include <string.h>
- #endif
-
-
- //µ Parser::IParser
- #pragma segment Parser
- short Parser::IParser()
- {
- short err = fStack.IStack(100, 50);
-
- if (err != noErr)
- return (err);
-
- fStack.SetEmptyItem(&gPrsDeclList);
- Shift(&gPrsDeclList);
- fItemIndex = 0;
- fRecursionCount = 0;
- fDepth = 0;
- DebugParser(false);
-
- return (noErr);
- }
-
-
-
- // µ Parser::IParser
- #pragma segment Parser
- short Parser::IParser(const Parser *aParser)
- {
- short err = fStack.IStack(&aParser->fStack);
-
- if (err != noErr)
- return (err);
-
- fFormat = aParser->fFormat;
- fItemIndex = aParser->fItemIndex;
- fDebugParser = aParser->fDebugParser;
-
- return (noErr);
- }
-
-
-
- //µ Parser::~Parser
- #pragma segment Parser
- Parser::~Parser()
- {
- }
-
-
- //µ Parser::Parse
- #pragma segment Parser
- Boolean Parser::Parse(Syntactic *aToken)
- {
- /*
- ** If this is a comment, handle it immediately
- */
- if (aToken->IsLex()) {
- // Flush any identifiers which haven't been handled yet.
- if (aToken->IsSeparator())
- if (TopItem()->Type() == kSPrs_Id)
- if (!Parse())
- return (false);
-
- /*
- ** Handle any special forms here, those forms which are unambiguous and
- ** have but a single parse. In particular, ids can become part of
- ** operators (check if the top item on the parse stack is a Decl_Operator)
- ** or parsed ids (check if the top items is a Prs_Id).
- */
- switch (aToken->Type()) {
- case kSLex_DeclOperator:
- Shift(new PrsDeclOperator);
- break;
-
- case kSLex_Id:
- if (TopItem()->Type() == kSPrs_DeclOperator)
- break;
- // !!! FALL THROUGH !!!
-
- case kSLex_ClassColon:
- // Identifiers might be qualified, etc.
- if (TopItem()->Type() != kSPrs_Id)
- Shift(&gPrsId);
- break;
-
- default:
- break;
- }
- }
-
- /*
- ** Debugging counter: prevent multiple invocations of the parser.
- ** Incremented on entry, decremented on successful parse.
- */
- Boolean bumpRecursionCount = (Depth() >= fDepth);
- if (bumpRecursionCount) {
- if (++fRecursionCount >= 10) {
- fFormat->Flush();
- if (fDebugParser)
- DumpStack(gStderr);
- diag(kFatal, "\n\Recursion limit: token = %s\n", NameOf(aToken->Type()));
- }
- }
-
- /*
- ** Descend the stack looking for a taker. If one is found, then
- ** exit the routine. If one is not found, return false.
- */
- if (fDebugParser) {
- diag(kDebug, "\nEntry #%d Parser::Parse(%s)\n", fRecursionCount, NameOf(aToken->Type()));
- }
-
- for (int i = Depth(); i-- > 0;) {
- Syntactic * anItem = At(i);
-
- if (anItem->IsPrs()) {
- // Preserve the item index around calls to parsers
- short savedItemIndex = fItemIndex;
-
- fItemIndex = i; // Note this index
- fDepth = Depth(); // Note this depth
- if (((SyntacticPrs *)anItem)->Accept(aToken, this)) {
- fItemIndex = savedItemIndex; // Restore
- if (bumpRecursionCount)
- --fRecursionCount;
-
- if (fDebugParser) {
- if (fRecursionCount == 0)
- DumpStack(gStderr);
- }
-
- return (true);
- }
-
- fItemIndex = savedItemIndex; // Restore
- }
- }
-
- if (bumpRecursionCount)
- --fRecursionCount;
-
- return (false);
- }
-
-
- /*
- ** Flush any tokens being held by any parse states on the stack. Do this by
- ** parsing a token of type kSLex_Flush. Because this parse usually fails,
- ** preserve and restore fRecursionCount around the call to Parse(). Return
- ** true because we don't care.
- */
- //µ Parser::Parse
- #pragma segment Parser
- Boolean Parser::Parse()
- {
- //short count = fRecursionCount;
-
- Parse(&gLexFlush);
- //fRecursionCount = count;
- return (true);
- }
-
-
-
- //µ Parser::FindHandle
- #pragma segment Parser
- short Parser::FindHandle(short aTokenType, const short *aStackDescription) const
- {
- int stackDepth = Depth();
-
- // aStackDescription is of the form
- // <value> <tokenType> <n> {<n>*<v>}
- // with the terminating condition of
- // (? < 0) <ignored> 0
- for (;;) {
- short aValue = *aStackDescription++;
- short aType = *aStackDescription++;
- short nItems = *aStackDescription++;
- const short *nextDescription = &aStackDescription[nItems];
-
- // Match the token type first, as that is cheapest. In case of
- // mismatch, check nItems for 0. If it is 0, then this was the
- // last handle description. Note that if this is the last handle
- // description but that the token types matched, that the loop
- // below will return true. Consequently, there is no need for a
- // separate check
-
- if (aValue < 0 && nItems == 0)
- return (aValue);
-
- if (aTokenType == aType || aType < 0) {
- // aStackDescription points to the deepest entry in the stack.
- // Consequently, start indexing from the bottom to the top.
- if (nItems <= stackDepth) {
- Boolean matched = true;
-
- // Check out the values.
- while (matched && nItems > 0) {
- matched = (Pick(--nItems)->Type() == *aStackDescription) || (*aStackDescription < 0);
- ++aStackDescription;
- }
-
- // If the stack matched, return the value
- if (matched)
- return (aValue);
- }
- }
-
- // The stack contents did not match the handle and there are more
- // handles to check. Advance to the next handle description
- aStackDescription = nextDescription;
- }
- }
-
-
- //µ Parser::DumpStack
- #pragma segment Parser
- void Parser::DumpStack(StdFile &aFile)
- {
- aFile.Puts("Dump of parse stack");
- aFile.Puts("-------------------\n");
- for (int i = 0; i < Depth(); i++) {
- short aType = At(i)->Type();
- char mark = (i == fItemIndex) ? '*' : ' ';
-
- aFile.Printf("%c %2d %-20s (%d)\n", mark, i, NameOf(aType), aType);
- }
- aFile.Flush();
- }
-
-
-
- #define CASE(a) case a: return (#a);
- #pragma segment Parser
- const char *Parser::NameOf(short aType)
- {
- switch (aType) {
- //ƒ-
- CASE(kSLex_EOF)
- CASE(kSLex_Id)
- CASE(kSLex_Value)
- CASE(kSLex_LParen)
- CASE(kSLex_RParen)
- CASE(kSLex_LBrace)
- CASE(kSLex_RBrace)
- CASE(kSLex_LCurly)
- CASE(kSLex_RCurly)
- CASE(kSLex_Op)
- CASE(kSLex_OpAssign)
- CASE(kSLex_Colon)
- CASE(kSLex_ClassColon)
- CASE(kSLex_SemiColon)
- CASE(kSLex_Comma)
- CASE(kSLex_Ellipsis)
- CASE(kSLex_Comment)
- CASE(kSLex_NewLine)
- CASE(kSLex_Null)
- CASE(kSLex_PoundLine)
- CASE(kSLex_Break)
- CASE(kSLex_Case)
- CASE(kSLex_Default)
- CASE(kSLex_Decl)
- CASE(kSLex_DeclOperator)
- CASE(kSLex_Do)
- CASE(kSLex_Else)
- CASE(kSLex_For)
- CASE(kSLex_If)
- CASE(kSLex_Struct)
- CASE(kSLex_Switch)
- CASE(kSLex_While)
- CASE(kSLex_Public)
-
- CASE(kSLex_ParsedId)
- CASE(kSLex_Flush)
- CASE(kSLex_Context)
-
- CASE(kSPrs_Id)
- CASE(kSPrs_StmtList)
- CASE(kSPrs_DeclList)
- CASE(kSPrs_DeclType)
- CASE(kSPrs_Stmt)
- CASE(kSPrs_Decl)
- CASE(kSPrs_Do)
- CASE(kSPrs_If)
- CASE(kSPrs_Else)
- CASE(kSPrs_For)
- CASE(kSPrs_Struct)
- CASE(kSPrs_Switch)
- CASE(kSPrs_While)
- CASE(kSPrs_Expr)
- CASE(kSPrs_DeclOperator)
- CASE(kSPrs_NewLine)
-
- default: return ("<unknown token>");
- //ƒ+
- }
- }
-
-
-